/*通过苹果笔记本的构造理解建造者模式*/
#include <iostream>
#include <string>
#include <memory>

// 抽象电脑类
class Computer{
    public:
        Computer() {}
        void setBoard(const std::string &board){
            _board = board;
        }
        void setDisplay(const std::string &display){
            _display = display;
        }
        virtual void setOs() = 0;

        void show(){
            std::cout << "主板: " << _board << std::endl;
            std::cout << "显示器: " << _display << std::endl;
            std::cout << "操作系统: " << _os << std::endl;
        }
    protected:
        std::string _board;     // 主板
        std::string _display;   // 显示器
        std::string _os;        // 操作系统
};

// 建造者接口
class Builder{
    public:
        virtual void buildBoard(const std::string &board) = 0;
        virtual void buildDisplay(const std::string &display) = 0;
        virtual void buildOs() = 0;
        virtual std::shared_ptr<Computer> build() = 0;
};

// 构造电脑时可能各个零部件有顺序要求，所以需要一个指挥者来指导建造过程
class Director{
    public:
        Director(Builder *builder):_builder(builder) {}
        void construct(const std::string &board, const std::string &display){
            _builder->buildBoard(board);        // 先装主板
            _builder->buildDisplay(display);    // 再装显示器
            _builder->buildOs();                // 最后装操作系统
        }
    private:
        std::shared_ptr<Builder> _builder;
};


// 只要是苹果操作系统，它的系统就是写死的
class MacBook : public Computer{
    public:
        void setOs() override{
            _os = "Mac OS x12";
        }
};

// 为苹果操作系统定制的建造者
class MacBookBuilder : public Builder{
    public:
        MacBookBuilder():_computer(new MacBook()){}
        void buildBoard(const std::string &board){
            _computer->setBoard(board);
        }
        void buildDisplay(const std::string &display){
            _computer->setDisplay(display);
        }
        void buildOs(){
            _computer->setOs();
        }
        std::shared_ptr<Computer> build(){
            return _computer;
        }
    private:
        std::shared_ptr<MacBook> _computer;
};


int main()
{
    Builder *builder = new MacBookBuilder();    // 创建一个苹果电脑建造者
    std::unique_ptr<Director> director(new Director(builder));
    director->construct("华硕主板", "三星显示器");
    std::shared_ptr<Computer> computer = builder->build();
    computer->show();
    return 0;
}